from ProjectTool.common_tool.random_func_tool import random_tool
from utils.base_response import BaseResponse
from collections import Iterable
import jsonpath
import re
import json


# 主要用于sql数据处理
class InParameter:
    def __init__(self, in_data, sql_data):
        '''
        # 输入数据转换
        :param in_data: 将要插入的数据
        :param sql_data: 被插入的模板
        '''
        self.in_data = in_data
        self.sql_data = sql_data
        self.res = BaseResponse()

    def run(self):
        if self.sql_data:
            if self.in_data:
                if isinstance(self.in_data, str):
                    self.in_data = json.loads(self.in_data)
                sql_list = re.findall('\{\w+\}', self.sql_data)  # 得到要交换的列表
                sql_dict = {key: '' for key in sql_list}  # 将列表转换成字典
                for key in sql_dict:  # 与源字符串进行数据交换
                    # dt = self.in_data.get(key.replace('{', '').replace('}', ''))
                    sql_key = key.strip('{}')
                    try:
                        value = self.in_data[sql_key]
                        self.sql_data = self.sql_data.replace(key, str(value))
                    except Exception as e:
                        self.res.status = 1
                        self.res.msg = '数据源中没有{key}'.format(key=key)
                        self.res.error = str(e.args)
        return self.sql_data


# 往url中插入Parameter数据
class URLInParameter:
    def __init__(self, out_url, url_dict):
        self.url_dict = url_dict
        self.out_url = out_url
        self.res = BaseResponse()

    def get_value(self):
        url_data = ''
        if isinstance(self.url_dict, dict):
            for key in self.url_dict:
                try:
                    url_str = str(key) + '=' + str(self.url_dict[key])
                    if url_data:
                        url_data += '&' + url_str
                    else:
                        url_data += url_str
                except Exception as e:
                    self.res.status = 1
                    self.res.msg = 'url参数拼接异常！'
                    self.res.error = str(e.args)
        else:
            self.res.status = 1
            self.res.msg = 'url_dict不是字典！'
        return url_data

    def run(self):
        if isinstance(self.out_url, str):
            url_data = self.get_value()
            if url_data:
                self.out_url += '?' + url_data
        else:
            self.res.status = 1
            self.res.msg = 'url不是字符串！'


# 从仓库中获取数据
class StepsData:
    def __init__(self, out_data, data_warehouse, steps_data):
        '''
        # 输出数据转换
        :param out_data: 输出数据模板
        :param sql_dict: 数据源
        '''
        self.out_data = out_data
        self.data_warehouse = data_warehouse
        self.steps_data = steps_data
        self.res = BaseResponse()

    def get_out_strs(self, out_str):
        lis = ['||', '+']
        dt = None
        for li in lis:
            out_strs = out_str.split(li)
            if li == '||':  # 或运算
                for out_data in out_strs:
                    out_data = out_data.strip()
                    dt, st = self.get_value(out_data)
                    if dt: break
            elif li == '+':  # 拼接运算
                dts = []  # 获取匹配到的值
                for out_data in out_strs:
                    out_data = out_data.strip()
                    value, st = self.get_value(out_data)
                    if value:
                        dts.append(str(value[0]))
                    else:
                        break
                else:
                    if len(dts) > 1:
                        dt = [''.join(dts)]
            else:
                self.res.status = 1
                self.res.msg = '模板格式有误：{out_str}'.format(out_str=out_str)
        return dt

    def get_value(self, out_str):
        status = True  # 是否匹配上了
        dt = None  # 获取到的数据
        if out_str.startswith('{$') and out_str.endswith('}'):  # 以jsonPASH取 步骤传入的值
            out_str = out_str.strip('{}')
            dt = jsonpath.jsonpath(self.steps_data, out_str)
        elif out_str.startswith('[') and out_str.endswith(']'):  # 取值需要逻辑计算
            out_str = out_str.strip('[]')
            dt = self.get_out_strs(out_str)
        elif out_str.startswith('$'):  # 以jsonPASH取 仓库中的值
            dt = jsonpath.jsonpath(self.data_warehouse, out_str)
        else:  # 输入格式无法解析
            status = False
        return dt, status

    def list_dictionary(self, dictionary):
        status = False
        for key in dictionary:
            if isinstance(dictionary, list):
                if isinstance(key, str) and len(dictionary) == 1:
                    status = True
                if isinstance(key, Iterable) and not isinstance(key, str):
                    self.list_dictionary(key)
            elif isinstance(dictionary, dict):
                value = dictionary.get(key)
                if isinstance(value, str):
                    dt, st = self.get_value(value)
                    if st:
                        if dt:
                            if len(dt) > 1:
                                self.res.status = 1
                                self.res.msg = '外层非列表，不能存下多个数据'
                                self.res.error = {value: dt}
                            else:
                                dictionary[key] = dt[0]  # 非列表时直接取第一个元素
                        else:
                            self.res.status = 1
                            self.res.msg = '{key}:{value}匹配失败'.format(key=key, value=value)
                            return
                elif isinstance(value, Iterable):
                    self.list_dictionary(value)
        if status:
            # key的外层如果时list，那么表达式key应加上 .*
            dt, st = self.get_value(key)
            if dt:
                for index, value in enumerate(dt):
                    if index == 0:
                        dictionary[0] = value
                    else:
                        dictionary.append(value)

    def run(self):
        try:
            if isinstance(self.out_data, str):
                self.out_data = json.loads(self.out_data)
        except Exception as e:
            self.res.status = 1
            self.res.msg = '模板转换字典失败'
            self.res.error = str(e.args)
        else:
            self.list_dictionary(self.out_data)

    def dict(self):
        self.run()
        return self.out_data


# 函数调用
class FuncParameter:
    def __init__(self, obj_data):
        self.obj_data = obj_data
        self.res = BaseResponse()

    def run(self):
        if self.obj_data:
            '''
            1.我要分离出函数
            2.我要函数执行
            3.将执行结果替换回原来的位置
            '''
            # func_list = re.findall('\{\w+\[\d+:?\d*\]\}', self.obj_data)  # 匹配到对应的函数以及参数
            func_list = re.findall('{\w+\[[\w:.]+\]}', self.obj_data)  # 匹配到对应的函数以及参数
            func_dict = {lis: re.findall('[A-Za-z_]+|\d+\.?\d*', lis) for lis in func_list}
            for key in func_dict:
                func_str = func_dict[key][0]
                parameter = func_dict[key][1:]
                try:
                    func = getattr(random_tool, func_str)  # 获取函数
                    value, status = func(*parameter)  # 传参运行并取值
                    if status:
                        self.res.status = 1
                        self.res.msg = '函数（{key}）执行异常'.format(key=key)
                        break
                    if isinstance(value, str):
                        self.obj_data = self.obj_data.replace(key, value)
                    else:
                        self.obj_data = self.obj_data.replace('"%s"' % key, json.dumps(value))
                except Exception as e:
                    self.res.status = 1
                    self.res.msg = '（{key}）函数名或者传参有误'.format(key=key)
                    self.res.error = str(e.args)
                    break
        # return self.obj_data
